package com.leilbase.mspring.core;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class ClassScanner {

    public static List<Class<?>> scanClass(String packageName) throws IOException, ClassNotFoundException {
        List<Class<?>> classList = new ArrayList<Class<?>>();
        // 获取包路径
        String path = packageName.replace(".", "/");
        // 获取类加载器
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        // 获取路径下的资源
        Enumeration<URL> resources = classLoader.getResources(path);
        // 遍历资源
        while (resources.hasMoreElements()) {
            URL resource = resources.nextElement();
            String protocol = resource.getProtocol();
            // 获取资源类型，处理资源是jar包的情况
            if (protocol.equals("jar")) {
                JarURLConnection jarURLConnection = (JarURLConnection) resource.openConnection();
                String jarFilePath = jarURLConnection.getJarFile().getName();
                classList.addAll(getClassesFromJar(jarFilePath, path));
            } else if (protocol.equals("file")){
                // todo
                // 获取包路径的另一种方法
                String packagePath = URLDecoder.decode(resource.getFile(), "UTF-8");
                getClassesFromPath(packageName, packagePath, classList);
            }
        }
        return classList;
    }


    private static List<Class<?>> getClassesFromJar(String jarFilePath, String path) throws IOException, ClassNotFoundException {
        List<Class<?>> classList = new ArrayList<Class<?>>();
        JarFile jarFile = new JarFile(jarFilePath);
        Enumeration<JarEntry> entries = jarFile.entries();
        while (entries.hasMoreElements()) {
            JarEntry entry = entries.nextElement();
            String entryName = entry.getName();
            if (entryName.startsWith(path) && entryName.endsWith(".class")) {
                // 获取到类的全限定名
                String classFullName = entryName.replace("/", ".").substring(0, entryName.length()-6);
                classList.add(Class.forName(classFullName));
            }
        }
        return classList;
    }

    private static void getClassesFromPath(String packageName, String packagePath, List<Class<?>> classes) throws ClassNotFoundException {
        File dir = new File(packagePath);
        if (!dir.exists() || !dir.isDirectory()) {
            return;
        }
        File[] files = dir.listFiles(pathname -> pathname.isDirectory() || pathname.getName().endsWith(".class"));
        for (File file : files) {
            if (file.isDirectory()) {
                getClassesFromPath(packageName + "." + file.getName(),
                        file.getAbsolutePath(), classes);
            } else {
                String fileName = file.getName();
                String className = fileName.substring(0, fileName.length()-6);
                String classFullName = packageName + "." + className;
                classes.add(Class.forName(classFullName));
            }
        }
    }


}
